package b;

import h.RequestContext;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;

import d.ConnectionManager;
import d.DBUtils;
import d.QueryCallback;

public class News extends Entity {

	private String title = "";
	private String source = "";
	private String content = "";
	private Date createdOn = new Date();
	private String creatorName = "";
	private int creatorId;

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
	}

	public Date getCreatedOn() {
		return createdOn;
	}

	public void setCreatedOn(Date createdOn) {
		this.createdOn = createdOn;
	}

	public void setSource(String source) {
		this.source = source;
	}

	public String getSource() {
		return source;
	}

	public void setCreatorName(String creatorName) {
		if(creatorName==null){
			creatorName = "";
		}
		this.creatorName = creatorName;
	}

	public String getCreatorName() {
		return creatorName;
	}

	public void setCreatorId(int id) {
		creatorId = id;
	}
	
	public int getCreatorId() {
		return creatorId;
	}

	public static Iterator<Entity> list(RequestContext rc) {
		return ConnectionManager.executeQuery("SELECT News.id as id,title,source,content,User.name as creatorName,User.id as creatorId,createdOn FROM News LEFT OUTER JOIN User ON User.id=News.createdBy ORDER BY createdOn DESC", new QueryCallback<Iterator<Entity>>(){

			@Override
			public Iterator<Entity> processResultset(ResultSet rs) throws SQLException {
				LinkedList<Entity> ll = new LinkedList<Entity>();
				while(rs.next()) {
					ll.add(parseCurrentResult(rs));
				}
				return ll.iterator();
			}
		});
	}

	public static Entity create(RequestContext rc) {
		News n = new News();
		n.setCreatorId(rc.getCurrentUser().getId());
		n.setCreatorName(rc.getCurrentUser().getName());
		return n;
	}

	public static Entity retrieve(int uniqueId) {
		News news = ConnectionManager.executeQuery("SELECT News.id as id,title,source,content,User.name as creatorName,User.id as creatorId,createdOn FROM News LEFT OUTER JOIN User ON User.id=News.createdBy WHERE News.id=?", new QueryCallback<News>(){
			@Override
			public News processResultset(ResultSet rs) throws SQLException {
				News n = null;
				if(rs.next()) {
					n = parseCurrentResult(rs);
				}
				return n;
			}
		}, uniqueId);

		return news;
	}

	@Override
	public boolean save() {
		if(this.getId()==Integer.MIN_VALUE) {
			return insert();
		} else {
			return ConnectionManager.executeUpdate(
					"UPDATE News SET title=?,source=?,content=? WHERE id=?",
					this.getTitle(),this.getSource(),this.getContent(),this.getId());
		}
	}

	private static News parseCurrentResult(ResultSet rs) {
		News n = new News();
		try {
			n.setId(rs.getInt("id"));
			n.setTitle(rs.getString("title"));
			n.setContent(rs.getString("content"));
			n.setSource(rs.getString("source"));
			n.setCreatorName(rs.getString("creatorName"));
			n.setCreatorId(rs.getInt("creatorId"));
			n.setCreatedOn(rs.getTimestamp("createdOn"));
		}catch(SQLException e){
			e.printStackTrace();
			n = null;
		}

		return n;
	}
	
	private boolean insert(){
		boolean done = false;
		Connection conn = ConnectionManager.getConnection();
		try {
			conn.setAutoCommit(false);
			conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);

			PreparedStatement ps = conn.prepareStatement("INSERT INTO News (title,source,content,createdBy,createdOn) VALUES (?,?,?,?,?);");
			ps.setObject(1, this.getTitle());
			ps.setObject(2, this.getSource());
			ps.setObject(3, this.getContent());
			ps.setObject(4, this.getCreatorId());
			ps.setObject(5, DBUtils.datetimeFormat.format(this.getCreatedOn()));
			ps.executeUpdate();

			ps = conn.prepareStatement("SELECT LAST_INSERT_ID() AS id FROM News");
			ResultSet rs = ps.executeQuery();
			if(rs.next()) {
				this.setId(rs.getInt(1));
			}

			conn.commit();
			done = true;
		} catch (SQLException e) {
			e.printStackTrace();
			this.setId(Integer.MIN_VALUE);
			try {
				conn.rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
		}
		ConnectionManager.freeConnection(conn);
		return done;
	}

	@Override
	public void update(Map<String, String> params) {
		if(params.containsKey("title")) {
			this.setTitle(params.get("title"));
		}

		if(params.containsKey("source")) {
			this.setSource(params.get("source"));
		}

		if(params.containsKey("content")) {
			this.setContent(params.get("content"));
		}
	}

}
